<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>django自定义日志 | Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="自定义日志">
<meta property="og:type" content="article">
<meta property="og:title" content="django自定义日志">
<meta property="og:url" content="http://example.com/2021/03/13/django%E8%87%AA%E5%AE%9A%E4%B9%89%E6%97%A5%E5%BF%97/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="自定义日志">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2021-03-13T14:09:56.894Z">
<meta property="article:modified_time" content="2021-03-13T14:18:07.129Z">
<meta property="article:author" content="John Doe">
<meta property="article:tag" content="学习笔记">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-django自定义日志" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2021/03/13/django%E8%87%AA%E5%AE%9A%E4%B9%89%E6%97%A5%E5%BF%97/" class="article-date">
  <time class="dt-published" datetime="2021-03-13T14:09:56.894Z" itemprop="datePublished">2021-03-13</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/django/">django</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="p-name article-title" itemprop="headline name">
      django自定义日志
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <p>日志模块需要配置4个部分</p>
<h4 id="1-loggers"><a href="#1-loggers" class="headerlink" title="1 loggers"></a>1 loggers</h4><p>logger是日志的入口，可以配置日志的级别，描述该logger可以处理的日志的严重程度。每一条写入logger的消息就是一条日志记录，每一条日志记录也包含日志级别，当logger处理一条消息时，会将自身级别与该条日志的级别做对比，如果该条日志的级别等于或高于logger的级别，那么就会被进一步处理，否则该条日志就会被忽略。当logger确定处理一条日志后，会把它传给handler。日志级别定义如下：</p>
<ul>
<li><code>DEBUG</code>：排查故障时使用的低级别系统信息</li>
<li><code>INFO</code>：一般的系统信息</li>
<li><code>WARNING</code>：描述系统发生了一些小问题的信息</li>
<li><code>ERROR</code>：描述系统发生了大问题的信息</li>
<li><code>CRITICAL</code>：描述系统发生严重问题的信息</li>
</ul>
<h4 id="2-handlers"><a href="#2-handlers" class="headerlink" title="2 handlers"></a>2 handlers</h4><p>handler是决定如何处理logger中每一条消息的引擎。它描述特定的日志行为，把消息输出到屏幕、文件或者网络socket。handler也有日志级别的概念，如果一条日志记录的级别不匹配或低于handler的日志级别，对应的消息就会被handler忽略。一个logger可以有多个handler，每一个handler可以有不同的日志级别。这样就可以根据消息重要性的不同来提供不同格式的输出。handlers可以配置如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">LOGGING = &#123;</span><br><span class="line">	...</span><br><span class="line">    <span class="string">&#x27;handlers&#x27;</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;console&#x27;</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;level&#x27;</span>: <span class="string">&#x27;INFO&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;filters&#x27;</span>: [<span class="string">&#x27;require_debug_true&#x27;</span>],</span><br><span class="line">            <span class="string">&#x27;class&#x27;</span>: <span class="string">&#x27;logging.StreamHandler&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;formatter&#x27;</span>: <span class="string">&#x27;simple&#x27;</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&#x27;mail_admins&#x27;</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;level&#x27;</span>: <span class="string">&#x27;ERROR&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;class&#x27;</span>: <span class="string">&#x27;django.utils.log.AdminEmailHandler&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;filters&#x27;</span>: [<span class="string">&#x27;special&#x27;</span>]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以在‘hanlers’中添加自定义的handler。handler各参数定义如下:</p>
<table>
<thead>
<tr>
<th>参数名称</th>
<th>定义</th>
</tr>
</thead>
<tbody><tr>
<td>level</td>
<td>定义该handler可以匹配的日志级别</td>
</tr>
<tr>
<td>class</td>
<td>指定使用哪个类，python中提供了多个handlers的类，自定义时也可以继承这些类进行相应的修改。<br />StreamHandler，位于logging.StreamHandler。将日志信息输出到sys.stout, sys.stderr或者类文件对象，只有一个参数<code>class logging.StreamHandler(stream=None)</code>，如果<code>stream</code>为空则默认输出到sys.stderr上。<br />FileHandler，位于logging.FileHandler。继承StreamHandler，将日志信息输出到磁盘文件上。参数如下：<code>class logging.FileHandler(filename, mode=&#39;a&#39;, encoding=None, delay=False)</code>，<br />除此之外，还有NullHandler、WatchedFileHandler、RotatingFileHandler、TimedRotatingFileHandler、SocketHandler、DatagramHandler、SysLogHandler、NtEventHandler、SMTPHandler、MemoryHandler、HTTPHandler等等，具体可以参考python的官方文档<a target="_blank" rel="noopener" href="https://docs.python.org/3.8/library/logging.handlers.html">https://docs.python.org/3.8/library/logging.handlers.html</a></td>
</tr>
<tr>
<td>filters</td>
<td>指定过滤器</td>
</tr>
<tr>
<td>formatter</td>
<td>指定日志格式</td>
</tr>
<tr>
<td>其他参数</td>
<td>handler类中需要指定的参数，例如’filename’,’encoding’等</td>
</tr>
</tbody></table>
<h4 id="3-filters"><a href="#3-filters" class="headerlink" title="3 filters"></a>3 filters</h4><p>在日志记录从logger传到handler的过程中，可以使用filter来做额外的控制。</p>
<p>默认情况下，只要级别匹配，任何日志消息都会被处理。不过也可以通过filter来给日志处理增加额外的条件，例如可以添加一个filter只允许某个特定来源的ERROR消息输出。filter在django中的定义格式如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">LOGGING = &#123;</span><br><span class="line">	...</span><br><span class="line">    <span class="string">&#x27;filters&#x27;</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;special&#x27;</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;()&#x27;</span>: <span class="string">&#x27;optimize.filters.SpecialFilter&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;foo&#x27;</span>: <span class="string">&#x27;bar&#x27;</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&#x27;require_debug_true&#x27;</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;()&#x27;</span>: <span class="string">&#x27;django.utils.log.RequireDebugTrue&#x27;</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>filters</code>里面可以定义多个过滤器，<code>()</code>后面跟的时过滤器类的位置，过滤器类内容如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RequireDebugFalse</span>(<span class="params">logging.Filter</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">filter</span>(<span class="params">self, record</span>):</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">not</span> settings.DEBUG</span><br></pre></td></tr></table></figure>

<p>自定义的过滤器类也只需要重写以下<code>filter</code>方法即可，这个方法只会返回<code>True</code>或<code>False</code>，返回<code>False</code>时不处理，返回<code>True</code>时会过滤掉此条日志。</p>
<h4 id="4-格式器formatter"><a href="#4-格式器formatter" class="headerlink" title="4 格式器formatter"></a>4 格式器formatter</h4><p>格式器用来规定每条日志的格式，一个格式器通常由包含LogRecord attributes的python格式化字符串组成，也可以自行配置特定合适的格式器。LogRecord attributes包含以下内容</p>
<table>
<thead>
<tr>
<th align="left">Attribute name</th>
<th align="left">Format</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody><tr>
<td align="left">args</td>
<td align="left">You shouldn’t need to format this yourself.</td>
<td align="left">The tuple of arguments merged into <code>msg</code> to produce <code>message</code>, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).</td>
</tr>
<tr>
<td align="left">asctime</td>
<td align="left"><code>%(asctime)s</code></td>
<td align="left">Human-readable time when the <a target="_blank" rel="noopener" href="https://docs.python.org/3/library/logging.html#logging.LogRecord"><code>LogRecord</code></a> was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).</td>
</tr>
<tr>
<td align="left">created</td>
<td align="left"><code>%(created)f</code></td>
<td align="left">Time when the <a target="_blank" rel="noopener" href="https://docs.python.org/3/library/logging.html#logging.LogRecord"><code>LogRecord</code></a> was created (as returned by <a target="_blank" rel="noopener" href="https://docs.python.org/3/library/time.html#time.time"><code>time.time()</code></a>).</td>
</tr>
<tr>
<td align="left">exc_info</td>
<td align="left">You shouldn’t need to format this yourself.</td>
<td align="left">Exception tuple (à la <code>sys.exc_info</code>) or, if no exception has occurred, <code>None</code>.</td>
</tr>
<tr>
<td align="left">filename</td>
<td align="left"><code>%(filename)s</code></td>
<td align="left">Filename portion of <code>pathname</code>.</td>
</tr>
<tr>
<td align="left">funcName</td>
<td align="left"><code>%(funcName)s</code></td>
<td align="left">Name of function containing the logging call.</td>
</tr>
<tr>
<td align="left">levelname</td>
<td align="left"><code>%(levelname)s</code></td>
<td align="left">Text logging level for the message (<code>&#39;DEBUG&#39;</code>, <code>&#39;INFO&#39;</code>, <code>&#39;WARNING&#39;</code>, <code>&#39;ERROR&#39;</code>, <code>&#39;CRITICAL&#39;</code>).</td>
</tr>
<tr>
<td align="left">levelno</td>
<td align="left"><code>%(levelno)s</code></td>
<td align="left">Numeric logging level for the message (<code>DEBUG</code>, <code>INFO</code>, <code>WARNING</code>, <code>ERROR</code>, <code>CRITICAL</code>).</td>
</tr>
<tr>
<td align="left">lineno</td>
<td align="left"><code>%(lineno)d</code></td>
<td align="left">Source line number where the logging call was issued (if available).</td>
</tr>
<tr>
<td align="left">message</td>
<td align="left"><code>%(message)s</code></td>
<td align="left">The logged message, computed as <code>msg % args</code>. This is set when <a target="_blank" rel="noopener" href="https://docs.python.org/3/library/logging.html#logging.Formatter.format"><code>Formatter.format()</code></a> is invoked.</td>
</tr>
<tr>
<td align="left">module</td>
<td align="left"><code>%(module)s</code></td>
<td align="left">Module (name portion of <code>filename</code>).</td>
</tr>
<tr>
<td align="left">msecs</td>
<td align="left"><code>%(msecs)d</code></td>
<td align="left">Millisecond portion of the time when the <a target="_blank" rel="noopener" href="https://docs.python.org/3/library/logging.html#logging.LogRecord"><code>LogRecord</code></a> was created.</td>
</tr>
<tr>
<td align="left">msg</td>
<td align="left">You shouldn’t need to format this yourself.</td>
<td align="left">The format string passed in the original logging call. Merged with <code>args</code> to produce <code>message</code>, or an arbitrary object (see <a target="_blank" rel="noopener" href="https://docs.python.org/3/howto/logging.html#arbitrary-object-messages">Using arbitrary objects as messages</a>).</td>
</tr>
<tr>
<td align="left">name</td>
<td align="left"><code>%(name)s</code></td>
<td align="left">Name of the logger used to log the call.</td>
</tr>
<tr>
<td align="left">pathname</td>
<td align="left"><code>%(pathname)s</code></td>
<td align="left">Full pathname of the source file where the logging call was issued (if available).</td>
</tr>
<tr>
<td align="left">process</td>
<td align="left"><code>%(process)d</code></td>
<td align="left">Process ID (if available).</td>
</tr>
<tr>
<td align="left">processName</td>
<td align="left"><code>%(processName)s</code></td>
<td align="left">Process name (if available).</td>
</tr>
<tr>
<td align="left">relativeCreated</td>
<td align="left"><code>%(relativeCreated)d</code></td>
<td align="left">Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.</td>
</tr>
<tr>
<td align="left">stack_info</td>
<td align="left">You shouldn’t need to format this yourself.</td>
<td align="left">Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.</td>
</tr>
<tr>
<td align="left">thread</td>
<td align="left"><code>%(thread)d</code></td>
<td align="left">Thread ID (if available).</td>
</tr>
<tr>
<td align="left">threadName</td>
<td align="left"><code>%(threadName)s</code></td>
<td align="left">Thread name (if available).</td>
</tr>
</tbody></table>
<p>配置formatter时，可以采用下列形式，在setting.py中添加</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">LOGGING = &#123;</span><br><span class="line">	...</span><br><span class="line">    <span class="string">&#x27;formatters&#x27;</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;verbose&#x27;</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;format&#x27;</span>: <span class="string">&#x27;&#123;levelname&#125; &#123;asctime&#125; &#123;module&#125; &#123;process:d&#125; &#123;thread:d&#125; &#123;message&#125;&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;style&#x27;</span>: <span class="string">&#x27;&#123;&#x27;</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&#x27;simple&#x27;</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;format&#x27;</span>: <span class="string">&#x27;&#123;levelname&#125; &#123;message&#125;&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;style&#x27;</span>: <span class="string">&#x27;&#123;&#x27;</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>




      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2021/03/13/django%E8%87%AA%E5%AE%9A%E4%B9%89%E6%97%A5%E5%BF%97/" data-id="ckm7t5pcx0002hott7qcee3bc" data-title="django自定义日志" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/" rel="tag">学习笔记</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2021/03/13/224.%E5%9F%BA%E6%9C%AC%E8%AE%A1%E7%AE%97%E5%99%A8/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          基本计算器
        
      </div>
    </a>
  
  
    <a href="/2021/03/13/sqlldr%E5%AF%BC%E5%85%A5%E5%A4%A7%E9%87%8F%E6%95%B0%E6%8D%AE%E5%88%B0oracle%E6%95%B0%E6%8D%AE%E5%BA%93/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">使用sqlldr导入上亿条数据到oracle中</div>
    </a>
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/SCIP/">SCIP</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/django/">django</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/leetcode/">leetcode</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/oracle/">oracle</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/" rel="tag">学习笔记</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/" style="font-size: 10px;">学习笔记</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/03/">March 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/03/13/224.%E5%9F%BA%E6%9C%AC%E8%AE%A1%E7%AE%97%E5%99%A8/">基本计算器</a>
          </li>
        
          <li>
            <a href="/2021/03/13/django%E8%87%AA%E5%AE%9A%E4%B9%89%E6%97%A5%E5%BF%97/">django自定义日志</a>
          </li>
        
          <li>
            <a href="/2021/03/13/sqlldr%E5%AF%BC%E5%85%A5%E5%A4%A7%E9%87%8F%E6%95%B0%E6%8D%AE%E5%88%B0oracle%E6%95%B0%E6%8D%AE%E5%BA%93/">使用sqlldr导入上亿条数据到oracle中</a>
          </li>
        
          <li>
            <a href="/2021/03/13/windows%E7%8E%AF%E5%A2%83%E4%B8%8B%E5%AE%89%E8%A3%85pyscipopt/">windows下安装pyscipopy</a>
          </li>
        
          <li>
            <a href="/2021/03/13/hello-world/">Hello World</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2021 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/js/jquery-3.4.1.min.js"></script>



  
<script src="/fancybox/jquery.fancybox.min.js"></script>




<script src="/js/script.js"></script>





  </div>
</body>
</html>